#include "SceneLoader.h"
#include <iostream>

using namespace std;

SceneLoader::SceneLoader(const char * fileName): doc( fileName )
{
  // Read string from file
	bool loadOkay = doc.LoadFile();
	if ( !loadOkay )
	{
	  printf( "Could not load test file %s. Error='%s'. Exiting.\n", fileName, doc.ErrorDesc() );
	  throw exception();
	}
	this->root = doc.RootElement();
}

//-------------------------------------------------------

bool SceneLoader::loadScene()
{
	sceneElement = root->FirstChildElement( "scene" );
	viewsElement = root->FirstChildElement( "views" );
	lightsElement = root->FirstChildElement( "lights" );
	texturesElement = root->FirstChildElement( "textures" );
	materialsElement = root->FirstChildElement( "materials" );
	transformationsElement = root->FirstChildElement( "transformations" );
	primitivesElement = root->FirstChildElement("primitives");
	componentsElement = root->FirstChildElement( "components" );
	illuminationElement = root->FirstChildElement("illumination");

	if(sceneElement == NULL)
	{
		cout << "Bloco Scene nao encontrado\n";
		return false;
	}
	else if (viewsElement == NULL) {
		cout << "Bloco Views nao encontrado\n";
		return false;
	}
	else if(lightsElement == NULL) {
		cout << "Bloco Lights nao encontrado\n";
		return false;
	}
	else if(texturesElement == NULL) {
		cout << "Bloco Textures nao encontrado\n";
		return false;
	}
	else if(materialsElement == NULL) {
		cout << "Bloco Materials nao encontrado\n";
		return false;
	}
	else if(transformationsElement == NULL) {
		cout << "Bloco Transformations nao encontrado\n";
		return false;
	}
	else if(primitivesElement == NULL) {
		cout << "Bloco Primitives nao encontrado\n";
		return false;
	}
	else if(componentsElement == NULL) {
		cout << "Bloco Components nao encontrado\n";
		return false;
	}
	else if(illuminationElement == NULL)
	{
		cout << "Bloco Illumination nao encontrado\n";
		return false;
	}
	else {
		loadSceneInfo();
		loadViews();
		loadLights();
		loadIllumination();
		loadTextures();
		loadMaterials();
		loadTransformations();
		loadPrimitives();
		loadComponents();
		return true;
	}
}

void SceneLoader::loadIllumination()
{
	i = new Illumination();
	int doublesided, local;
	if(illuminationElement->QueryIntAttribute("local", &local) == TIXML_SUCCESS &&
		illuminationElement->QueryIntAttribute("doublesided", &doublesided) == TIXML_SUCCESS)
	{
		i->setValues(doublesided,local);
	}
	for(TiXmlElement *child(illuminationElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "ambient")
		{
			float r,g,b,a;
			if(child->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("b", &b) == TIXML_SUCCESS && 
				child->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
			{
				i->setAmbient(r,g,b,a);
			}
		}
		else if(name == "background")
		{
			float r,g,b,a;
			if(child->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("b", &b) == TIXML_SUCCESS && 
				child->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
			{
				i->setBackground(r,g,b,a);
			}
		}
	}	
}

void SceneLoader::loadSceneInfo()
{
	s = new Scene();
	const string rootComponent = sceneElement->Attribute("root");
	float lengthAxis;
	if(sceneElement->QueryFloatAttribute("axis_length", &lengthAxis) == TIXML_SUCCESS)
	{
		s->setID(rootComponent);
		s->setLengthAxis(lengthAxis);
	}
}

void SceneLoader::loadPrimitives() {
	for(TiXmlElement *child(primitivesElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "primitive") {
			Primitive* prim = new Primitive();
			for(TiXmlElement *child2(child->FirstChildElement()); child2 != NULL; child2 = child2->NextSiblingElement())
			{
				const string nameChild(child2->Value());
				if(nameChild == "rectangle") 
				{
					Rectangle* rect = new Rectangle();
					if(prim->getMatInherit())
					{
						rect->setMatInherit(true);
						rect->setNoMat(false);
					}
					else if(prim->getNoMat())
					{
						rect->setNoMat(true);
						rect->setMatInherit(false);
					}
					else
					{
						rect->setNoMat(false);
						rect->setMatInherit(false);
						Material* mat = prim->getMat();
						rect->setmat(mat);
					}

					if(prim->getTexInherit())
					{
						rect->setTexInherit(true);
						rect->setNoTex(false);
					}
					else if(prim->getNoTex())
					{
						rect->setNoTex(true);
					}else
					{
						rect->setNoTex(false);
						rect->setTexInherit(false);
						Texture* tex = prim->getTex();
						rect->setTex(tex);
					}

					rect->setID(child->Attribute("id"));
					float x1, y1, x2, y2;
					if(child2->QueryFloatAttribute("x1", &x1) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y1", &y1) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("x2", &x2) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y2", &y2) == TIXML_SUCCESS)
					{
						rect->calculateCoordinates(x1,y1,x2,y2);
						primitivesMap[rect->getID()] = rect;
					}
				}else if(nameChild == "cylinder")
				{
					Cylinder* cylinder = new Cylinder();
					if(prim->getMatInherit())
					{
						cylinder->setMatInherit(true);
						cylinder->setNoMat(false);
					}else if(prim->getNoMat())
					{
						cylinder->setNoMat(true);
						cylinder->setMatInherit(false);
					}else
					{
						cylinder->setNoMat(false);
						cylinder->setMatInherit(false);
						Material* mat = prim->getMat();
						cylinder->setmat(mat);
					}

					if(prim->getTexInherit())
					{
						cylinder->setTexInherit(true);
						cylinder->setNoTex(false);
					}else if(prim->getNoTex())
					{
						cylinder->setNoTex(true);
						cylinder->setTexInherit(false);
					}else
					{
						cylinder->setNoTex(false);
						cylinder->setTexInherit(false);
						Texture* tex = prim->getTex();
						cylinder->setTex(tex);
					}

					cylinder->setID(child->Attribute("id"));
					GLUquadric *glQ = gluNewQuadric();
					cylinder->setQuadric(glQ);
					float base, top, height;
					int slices, stacks;
					if(child2->QueryFloatAttribute("base", &base) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("top", &top) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("height", &height) == TIXML_SUCCESS &&
						child2->QueryIntAttribute("slices", &slices) == TIXML_SUCCESS &&
						child2->QueryIntAttribute("stacks", &stacks) == TIXML_SUCCESS)
					{
						cylinder->setValues(base, top, height, slices, stacks);
						primitivesMap[cylinder->getID()] = cylinder;
					}
				}else if(nameChild == "sphere")
				{
					Sphere* sphere = new Sphere();
					if(prim->getMatInherit())
					{
						sphere->setMatInherit(true);
						sphere->setNoMat(false);
					}else if(prim->getNoMat())
					{
						sphere->setNoMat(true);
						sphere->setMatInherit(false);
					}else
					{
						sphere->setNoMat(false);
						sphere->setMatInherit(false);
						Material* mat = prim->getMat();
						sphere->setmat(mat);
					}

					if(prim->getTexInherit())
					{
						sphere->setTexInherit(true);
						sphere->setNoTex(false);
					}else if(prim->getNoTex())
					{
						sphere->setNoTex(true);
						sphere->setTexInherit(false);
					}else
					{
						sphere->setNoTex(false);
						sphere->setTexInherit(false);
						Texture* tex = prim->getTex();
						sphere->setTex(tex);
					}
					sphere->setID(child->Attribute("id"));
					GLUquadric *glQ = gluNewQuadric();
					sphere->setQuadric(glQ);
					float radius;
					int slices, stacks;
					if(child2->QueryFloatAttribute("radius", &radius) == TIXML_SUCCESS &&
						child2->QueryIntAttribute("slices", &slices) == TIXML_SUCCESS &&
						child2->QueryIntAttribute("stacks", &stacks) == TIXML_SUCCESS)
					{	
						sphere->setValues(radius, slices, stacks);
						primitivesMap[sphere->getID()] = sphere;
					}
				}else if(nameChild == "torus")
				{
					Torus* torus = new Torus();
					if(prim->getMatInherit())
					{
						torus->setMatInherit(true);
						torus->setNoMat(false);
					}else if(prim->getNoMat())
					{
						torus->setNoMat(true);
						torus->setMatInherit(false);
					}else
					{
						torus->setNoMat(false);
						torus->setMatInherit(false);
						Material* mat = prim->getMat();
						torus->setmat(mat);
					}

					if(prim->getTexInherit())
					{
						torus->setTexInherit(true);
						torus->setTexInherit(false);
					}else if(prim->getNoTex())
					{
						torus->setNoTex(true);
						torus->setTexInherit(false);
					}else
					{
						torus->setNoTex(false);
						torus->setTexInherit(false);
						Texture* tex = prim->getTex();
						torus->setTex(tex);
					}
					torus->setID(child->Attribute("id"));
					float innerRadius, outterRadius;
					int nsides, rings;
					if(child2->QueryFloatAttribute("inner", &innerRadius) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("outer", &outterRadius) == TIXML_SUCCESS &&
						child2->QueryIntAttribute("slices", &nsides) == TIXML_SUCCESS &&
						child2->QueryIntAttribute("loops", &rings) == TIXML_SUCCESS)
					{	
						torus->setValues(innerRadius, outterRadius, nsides, rings);
						primitivesMap[torus->getID()] = torus;
					}	
				}else if(nameChild == "triangle")
				{
					Triangle* triangle = new Triangle();
					if(prim->getMatInherit())
					{
						triangle->setMatInherit(true);
						triangle->setNoMat(false);
					}else if(prim->getNoMat())
					{
						triangle->setNoMat(true);
						triangle->setMatInherit(false);
					}else
					{
						triangle->setNoMat(false);
						triangle->setMatInherit(false);
						Material* mat = prim->getMat();
						triangle->setmat(mat);
					}

					if(prim->getTexInherit())
					{
						triangle->setTexInherit(true);
						triangle->setNoTex(false);
					}else if(prim->getNoTex())
					{
						triangle->setNoTex(true);
						triangle->setTexInherit(false);
					}else
					{
						triangle->setNoTex(false);
						triangle->setTexInherit(false);
						Texture* tex = prim->getTex();
						triangle->setTex(tex);
					}

					triangle->setID(child->Attribute("id"));
					float x1, x2, x3, y1, y2, y3, z1, z2, z3;
					if(child2->QueryFloatAttribute("x1", &x1) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y1", &y1) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z1", &z1) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("x2", &x2) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y2", &y2) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z2", &z2) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("x3", &x3) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y3", &y3) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z3", &z3) == TIXML_SUCCESS)
					{
						triangle->setValues(x1,y1,z1,x2,y2,z2,x3,y3,z3);
						primitivesMap[triangle->getID()] = triangle;
					}
				}
				else if(nameChild == "material")
				{
					const string curID = child2->Attribute("id");
					if(curID == "inherit")
					{
						prim->setMatInherit(true);
						prim->setNoMat(false);
					}
					else if (curID == "none")
					{
						prim->setNoMat(true);
						prim->setMatInherit(false);
					}
					else
					{
						prim->setNoMat(false);
						prim->setMatInherit(false);
						Material* mat = new Material();
						mat = materialsMap[curID];
						prim->setmat(mat);
					}
				}
				else if(nameChild == "texture")
				{
					const string curID = child2->Attribute("id");
					if(curID == "inherit")
					{
						prim->setTexInherit(true);
						prim->setNoTex(false);
					}
					else if (curID == "none")
					{
						prim->setNoTex(true);
						prim->setTexInherit(false);
					}
					else
					{
						prim->setNoTex(false);
						prim->setTexInherit(false);
						Texture* tex = new Texture();
						tex = texturesMap[curID];
						prim->setTex(tex);
					}
				}
			}
		}
	}
}

void SceneLoader::loadTransformations() 
{
	for(TiXmlElement *child(transformationsElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "transformation")
		{
			vector<Transformation*> tr;
			for(TiXmlElement *child2(child->FirstChildElement()); child2 != NULL; child2 = child2->NextSiblingElement())
			{
				const string nameChild(child2->Value());
				if(nameChild == "rotate")
				{
					Rotation* rot = new Rotation();
					rot->setID(child->Attribute("id"));
					string a;
					float angle;
					a = child2->Attribute("axis");
					if(child2->QueryFloatAttribute("angle", &angle) == TIXML_SUCCESS)
					{
						rot->setValues(a[0], angle);
						tr.push_back(rot);
					}
				}
				else if(nameChild == "translate")
				{
					Translation* trans = new Translation();
					trans->setID(child->Attribute("id"));
					float x,y,z;
					if(child2->QueryFloatAttribute("x", &x) == TIXML_SUCCESS &&
							child2->QueryFloatAttribute("y", &y) == TIXML_SUCCESS &&
							child2->QueryFloatAttribute("z", &z) == TIXML_SUCCESS)
					{
							trans->setValues(x,y,z);
							tr.push_back(trans);
					}
				}
				else if(nameChild == "scale")
				{
					Scaling* scale = new Scaling();
					scale->setID(child->Attribute("id"));
					float x,y,z;
					if(child2->QueryFloatAttribute("x", &x) == TIXML_SUCCESS &&
							child2->QueryFloatAttribute("y", &y) == TIXML_SUCCESS &&
							child2->QueryFloatAttribute("z", &z) == TIXML_SUCCESS)
					{
							scale->setValues(x,y,z);
							tr.push_back(scale);
					}
				}
			}
			transformsMap[child->Attribute("id")] = tr;
		}
	}
}


void SceneLoader::loadMaterials() 
{
	for(TiXmlElement *child(materialsElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "material")
		{
			Material* mat = new Material();
			mat->setID(child->Attribute("id"));
			for(TiXmlElement *child2(child->FirstChildElement()); child2 != NULL; child2 = child2->NextSiblingElement())
			{
				const string nameChild(child2->Value());
				if(nameChild == "emission")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						mat->setEmission(r, g, b, a);
					}

				}else if(nameChild == "ambient")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						mat->setAmbient(r, g, b, a);
					}
				}else if(nameChild == "diffuse")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						mat->setDifuse(r, g, b, a);
					}
				}else if(nameChild == "specular")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						mat->setSpecular(r, g, b, a);
					}
				}else if(nameChild == "shininess")
				{
					float s;
					if(child2->QueryFloatAttribute("value", &s) == TIXML_SUCCESS)
					{
						mat->setShininess(s);
					}
				}
			}
			materialsMap[mat->getID()] = mat;
		}
	}
}

void SceneLoader::loadTextures() 
{
	GLuint texID = 1;
	for(TiXmlElement *child(texturesElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "texture")
		{
			const char* filename = child->Attribute("file");
			float ls, lt;
			if(child->QueryFloatAttribute("length_s", &ls) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("length_t", &lt) == TIXML_SUCCESS)
			{
				Texture* tex = new Texture(child->Attribute("id"), filename, texID, ls, lt);
				texturesMap[tex->getID()] = tex;
				texID++;
			}
		}
	}
}

void SceneLoader::loadLights()
{
	int lightID = 0;
	for(TiXmlElement *child(lightsElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "omni")
		{
			Omni* omni = new Omni();
			int enabled;
			omni->setID(child->Attribute("id"));
			if(child->QueryIntAttribute("enabled", &enabled)) omni->setEnabled(enabled);

			for(TiXmlElement *child2(child->FirstChildElement()); child2 != NULL; child2 = child2->NextSiblingElement())
			{
				const string nameChild(child2->Value());
				if(nameChild == "location")
				{
					float x,y,z,w;
					if(child2->QueryFloatAttribute("x", &x) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y", &y) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z", &z) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("w", &w) == TIXML_SUCCESS)
					{
						omni->setLocation(x,y,z,w);
					}

				}else if(nameChild == "ambient")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						omni->setAmbient(r, g, b, a);
					}
				}else if(nameChild == "diffuse")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						omni->setDiffuse(r, g, b, a);
					}
				}else if(nameChild == "specular")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						omni->setSpecular(r, g, b, a);
					}
				}
			}
			omni->setLightID(lightID);
			lightID++;
			lightsMap.push_back(omni);
		}
		else if(name == "spot")
		{
			Spot* spot = new Spot();
			int enabled;
			float angle, exponent;
			spot->setID(child->Attribute("id"));
			if(child->QueryIntAttribute("enabled", &enabled) &&
				child->QueryFloatAttribute("angle", &angle) &&
				child->QueryFloatAttribute("exponent", &exponent))
				{
					spot->setEnabled(enabled);
					spot->setAngle(angle);
					spot->setExponent(exponent);
				}

			for(TiXmlElement *child2(child->FirstChildElement()); child2 != NULL; child2 = child2->NextSiblingElement())
			{
				const string nameChild(child2->Value());
				if(nameChild == "location")
				{
					float x,y,z,w;
					if(child2->QueryFloatAttribute("x", &x) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y", &y) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z", &z) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("w", &w) == TIXML_SUCCESS)
					{
						spot->setLocation(x,y,z,w);
					}

				}else if(nameChild == "ambient")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						spot->setAmbient(r, g, b, a);
					}
				}else if(nameChild == "diffuse")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						spot->setDiffuse(r, g, b, a);
					}
				}else if(nameChild == "specular")
				{
					float r, g, b, a;
					if(child2->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
					{
						spot->setSpecular(r, g, b, a);
					}
				}else if(nameChild == "target")
				{
					float x,y,z;
					if(child2->QueryFloatAttribute("x", &x) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y", &y) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z", &z) == TIXML_SUCCESS)
					{
						spot->setTarget(x,y,z);
					}
				}
			}
			spot->setLightID(lightID);
			lightID++;
			lightsMap.push_back(spot);
		}
	}	
}

void SceneLoader::loadViews()
{
	for(TiXmlElement *child(viewsElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "ortho")
		{
			Ortho* ortho = new Ortho();
			float near, far, left, right, top, bottom;
			ortho->setID(child->Attribute("id"));
			if(child->QueryFloatAttribute("near", &near) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("far", &far) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("left", &left) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("right", &right) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("top", &top) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("bottom", &bottom) == TIXML_SUCCESS)
			{
				ortho->setValues(near, far, left, right, top, bottom);
			}
			ortho->convertToPointer();
			viewsMap.push_back(ortho);
		}
		else if(name == "perspective")
		{
			Perspective* pers = new Perspective();
			float near, far, angle;
			float fromX,fromY,fromZ;
			float toX,toY,toZ;
			pers->setID(child->Attribute("id"));
			if(child->QueryFloatAttribute("near", &near) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("far", &far) == TIXML_SUCCESS &&
				child->QueryFloatAttribute("angle", &angle) == TIXML_SUCCESS)
					pers->setFirst(near, far, angle);
			
			for(TiXmlElement *child2(child->FirstChildElement()); child2 != NULL; child2 = child2->NextSiblingElement())
			{
				const string nameChild(child2->Value());
				if(nameChild == "from")
				{
					if(child2->QueryFloatAttribute("x", &fromX) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y", &fromY) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z", &fromZ) == TIXML_SUCCESS)
							pers->setSecond(fromX, fromY, fromZ);
				}
				else if(nameChild == "to")
				{
					if(child2->QueryFloatAttribute("x", &toX) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("y", &toY) == TIXML_SUCCESS &&
						child2->QueryFloatAttribute("z", &toZ) == TIXML_SUCCESS)
							pers->setThird(toX, toY, toZ);
				}
			}
			pers->convertToPointer();
			viewsMap.push_back(pers);
		}
	}
}

void SceneLoader::loadComponents()
{
	for(TiXmlElement *child(componentsElement->FirstChildElement()); child != NULL; child = child->NextSiblingElement())
	{
		const string name(child->Value());
		if(name == "component")
		{
			Component* comp = new Component();
			comp->setID(child->Attribute("id"));
			for(TiXmlElement *child2(child->FirstChildElement()); child2 != NULL; child2 = child2->NextSiblingElement())
			{
				const string childName(child2->Value());
				if(childName == "transformation")
				{
					vector<Transformation*> trans;
					for(TiXmlElement *child3(child2->FirstChildElement()); child3 != NULL; child3 = child3->NextSiblingElement())
					{
						const string inTransform = child3->Value();
						if(inTransform == "transformationref")
						{
							const string transAtt = child3->Attribute("id");
							vector<Transformation*> t;
							t = transformsMap[transAtt];
							for(size_t i = 0; i < t.size(); i++)
								trans.push_back(t[i]);
						}
						else if(inTransform == "translate")
						{
							Translation* tr = new Translation();
							float x,y,z;
							if(child3->QueryFloatAttribute("x", &x) == TIXML_SUCCESS &&
									child3->QueryFloatAttribute("y", &y) == TIXML_SUCCESS &&
									child3->QueryFloatAttribute("z", &z) == TIXML_SUCCESS)
							{
									tr->setValues(x,y,z);
									trans.push_back(tr);
							}
						}
						else if(inTransform == "rotate")
						{
							Rotation* rot = new Rotation();
							string a;
							float angle;
							a = child3->Attribute("axis");
							if(child3->QueryFloatAttribute("angle", &angle) == TIXML_SUCCESS)
							{
								rot->setValues(a[0], angle);
								trans.push_back(rot);
							}
						}
						else if(inTransform == "scale")
						{
							Scaling* scale = new Scaling();
							scale->setID(child->Attribute("id"));
							float x,y,z;
							if(child3->QueryFloatAttribute("x", &x) == TIXML_SUCCESS &&
									child3->QueryFloatAttribute("y", &y) == TIXML_SUCCESS &&
									child3->QueryFloatAttribute("z", &z) == TIXML_SUCCESS)
							{
									scale->setValues(x,y,z);
									trans.push_back(scale);
							}
						}
					}
					comp->setTransforms(trans);
				}
				else if(childName == "materials")
				{
					vector<Material*> mats;
					if(child2->Attribute("key") != NULL)
					{
						const string key = child2->Attribute("key");
						comp->setKey(key[0]);
						for(TiXmlElement *child3(child2->FirstChildElement()); child3 != NULL; child3 = child3->NextSiblingElement())
						{
							string matAtt = child3->Attribute("id");
							if(matAtt == "inherit")
							{
								comp->setMaterialInherit(true);
							}
							else
							{
								comp->setMaterialInherit(false);
								Material* m = materialsMap[matAtt];
								mats.push_back(m);
							}
						}
						comp->setMaterialsColour(mats);
					}
					else
					{
						for(TiXmlElement *child3(child2->FirstChildElement()); child3 != NULL; child3 = child3->NextSiblingElement())
						{
							string matAtt = child3->Attribute("id");
							if(matAtt == "inherit")
							{
								comp->setMaterialInherit(true);
							}
							else
							{
								comp->setMaterialInherit(false);
								Material* m = materialsMap[matAtt];
								mats.push_back(m);
							}
						}
						comp->setMaterials(mats);
					}
				}
				else if(childName == "texture")
				{
					Texture* tex = new Texture();
					string texAtt = child2->Attribute("id");
					if(texAtt == "inherit")
					{
						comp->setTextureInherit(true);
						comp->setNoTexture(false);
					}
					else if(texAtt == "none")
					{
						comp->setNoTexture(true);
						comp->setTextureInherit(false);
					}
					else
					{
						comp->setTextureInherit(false);
						comp->setNoTexture(false);
						tex = texturesMap[texAtt];
					}
					comp->setTexture(tex);
				}
				else if(childName=="children")
				{
					vector<string> prims;
					vector<string> children;
					for(TiXmlElement *child3(child2->FirstChildElement()); child3 != NULL; child3 = child3->NextSiblingElement())
					{
						const string childAtt = child3->Value();
						if(childAtt == "primitiveref")
						{
							prims.push_back(child3->Attribute("id"));
						}
						else if(childAtt == "componentref")
						{
							children.push_back(child3->Attribute("id"));
						}
					}
					comp->setChildrenString(children);
					comp->setPrimitivesString(prims);
				}
			}
			componentsMap[comp->getID()] = comp;
		}
	}
}

void SceneLoader::runScene(bool change, char key)
{
	const string rootID = s->getID();
	Component* startingComponent = componentsMap[rootID];

	vector<Material*> voidVec;
	startingComponent->runComponent(NULL, voidVec, change, key);
}